如何测评中文Agent智能体?AgentCLUE基准方案发布!
AgentCLUE测评基准摘要
为更精确评估大语言模型(LLM)作为Agent的潜力,我们推出新的中文场景下的Agent测评基准AgentCLUE。该基准基于可执行的环境,在多轮对话中评估LLM作为执行代理,调用工具(函数)完成目标任务的能力。AgentCLUE基准测评方案具有以下要点:
1.AgentCLUE采用多轮对话的形式、具有可执行的测评环境、并且允许模型在与执行环境的交互中实现自我反思改进。2.AgentCLUE中包含了四个任务类型(常规多轮对话、函数缺失、参数缺失和长上下文干扰),可调用的功能函数覆盖多个现实场景,如文件系统、金融交易、智能车控、旅游等场景。3.AgentCLUE在获取模型回复时,支持Function Calling和Prompting两种调用模式。4.AgentCLUE基准中,针对每个测评题目会给出准确的函数调用作为ground truth,评价时,对比模型回复的函数调用结果和ground truth中的函数调用结果来评判模型回复是否正确。5.最终分数展示,将会包含一个总分和四个任务类别的得分;计划按照两种调用模式分别报告。详细的介绍将会在下面展开,我们同时在本文章的最后提供了参与测评的方式和AgentCLUE测评的时间计划。大语言模型(LLM)近年来取得了极大的进展,在各种任务中表现出色,例如数学、推理和编程等。然而,LLM作为Agent的潜力并未被充分开发。在Agent任务中,模型通常需要在迭代工作流程中执行更复杂的任务,如自我反思和优化输出、使用工具辅助决策、制定计划以完成目标任务。即使对于当今最先进的模型(例如,o1-preview)来说,这也是一项极具挑战性的任务。
为更精确评估大语言模型(LLM)作为Agent的潜力,我们推出了新的中文场景下的Agent测评 AgentCLUE。该基准基于可执行的环境,在多轮对话中评估LLM作为执行代理,调用工具(函数)完成目标任务的能力。在每轮对话中,LLM将与执行环境进行多次交互,根据环境的反馈进行自我反思并再次输出回答。在AgentCLUE基准中,对LLM准确理解任务需求并进行分解,准确规范的调用工具,在与执行环境交互中进行反思等能力提出更高的要求。
排行榜地址:www.SuperCLUEai.com
1. 特点
(1)可执行的评测环境
在与模型进行交互时,完成每个任务需要的函数功能均已经在测评环境中用代码实现。在从模型回复中提取的函数调用将会得到真正的执行,并且得到返回结果。
2. 任务划分和覆盖场景
AgentCLUE中包含了四个任务类型(常规多轮对话、函数缺失、参数缺失和长上下文干扰),涉及到多个现实场景的功能函数,如图:
"question":
["我是小李,请帮我检查一下当前目录是否在我名下,并列出当前目录中所有可见以及隐藏的内容",
"请转到“workspace”目录,并将其中一个“exp.txt”文件移动到新的目录:“spcl”。",
"再帮我检查一下“exp.txt”中是否出现关键字“宇宙”。"],
1.2 初始化系统参数
"initial_config":
{"ClueFileSystem":
{"root": {"小李": {"type": "directory",
"contents": {"workspace": {"type": "directory",
"contents": {
"exp.txt": {"type": "file", "content": "这是一个exp文件。\n 今天我们在这里欢聚一堂。\n为的是庆祝这一圆满的胜利成果!\n 我们终于完成了这一宇宙的壮举。"},
"spcl": {"type": "directory", "contents": {}},
".hidden_file": {"type": "file", "content": "这是隐藏文件。"}}}}}}}}
1.3 可调用函数列表(此处省略若干函数描述)
"tools": [{"type": "function",
"function": {"name": "cat",
"description": "该工具属于Clue文件系统。Clue文件系统一个简单的文件系统,允许用户执行基本的文件操作,例如导航目录,创建文件和目录,读取和写入文件等。工具说明:显示当前目录中任何扩展名的文件的内容。",
"parameters": {"type": "object", "properties": {"file_name": {"type": "string", "description": "当前目录显示文件的名称。不允许路径。"}},
"required": ["file_name"]},
"response": {"type": "dict", "properties": {"file_content": {"type": "string", "description": "文件的内容。"}}}}},
{"type":"function",
...},
省略若干函数描述]
1.4 准确的参考答案
[
// 第一轮问题的正确函数调用
["pwd()", "ls(a=True)"],
// 第二轮问题的正确函数调用
["cd(folder='workspace')", "mv(source='exp.txt',destination='spcl')"],
// 第三轮问题的正确函数调用
["cd(folder='spcl')", "grep(file_name='exp.txt',pattern='宇宙')"],
]
2.函数缺失
但在Function 缺失任务中,我们第一轮提供给模型的可调用函数调用列表中不会包含函数:pwd(), ls()。以此考察模型能否识别到缺少函数,无法完成任务。
任务示例:
例如针对下面的第二轮问题:“请执行详细搜索并识别相关部分”,此问题未指明“相关部分”的明确内容,这是必要参数,因此无法调用函数进行搜索。
[
// 第一轮问题
"将“Clue”目录中的“bisheng.pdf”移动到“Clue”目录中。确保创建“Clueai”目录。",
// 第二轮问题
"请执行详细搜索并识别相关部分。",
// 第三轮问题
"请对该pdf文件执行详细搜索并识别与“传统安全”相关的部分。"
]
4.长上下文干扰
保持多轮问答的交互形式,增加难度,发送模型的上下文中注入大量的干扰内容,考察模型在大量信息中捕捉主要目标的能力。
任务示例:
针对以下多轮问题:
{"question":
["我是小李,请帮我检查一下当前目录是否在我名下,并列出当前目录中所有可见以及隐藏的内容",
"请转到“workspace”目录,并将其中一个“exp.txt”文件移动到新的目录:“spcl”。",
"再帮我检查一下“exp.txt”中是否出现关键字“宇宙”。"],
"initial_config":
{"ClueFileSystem":
{"root": {"小李": {"type": "directory",
"contents": {"workspace": {"type": "directory",
"contents": {
"exp.txt": {"type": "file", "content": "这是一个exp文件。\n 今天我们在这里欢聚一堂。\n为的是庆祝这一圆满的胜利成果!\n 我们终于完成了这一宇宙的壮举。"},
"spcl": {"type": "directory", "contents": {}},
".hidden_file": {"type": "file", "content": "这是隐藏文件。"}}}}}}}}
}
Function Calling
此种调用方式将可调用的函数列表按照API接口的格式规范作为参数发送给模型,模型返回的函数调用内容将是规范的json字典格式。例如(以调用OpenAI的模型为例):
// 可调用的函数列表
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取当前天气",
"parameters": {...},
}
},
{
"type": "function",
"function": {
"name": "get_n_day_weather_forecast",
"description": "获取N天的天气预报",
"parameters": {...},
}
},
]
messages = [{"role":"user", "content":"我在北京.接下来五天的天气怎么样"}] # 用户的提问
tool_choice="auto" # 模型自己判断要不要调用函数
model="" # 指定模型
// 将用户的提问和可调用的函数列表发送给模型,模型自己判断要不要调用函数
response = client.chat.completions.create(
model=model,
messages=messages,
tools=tools,
tool_choice=tool_choice,
)
模型的返回结果格式如下:(tool_calls字段中为模型给出的函数调用,模型给出的函数调用结果为:
ChatCompletionMessage(content=None, role='assistant', function_call=None,
tool_calls=[ChatCompletionMessageToolCall(id='call_34PBraFdNN6KR95uD5rHF8Aw', function=Function(arguments='{"location":"北京","format":"celsius","num_days":5}', name='get_n_day_weather_forecast'), type='function')])
此种调用方式将可调用的函数列表拼接在文本中,通过messages参数发送给模型(如果支持设置system prompt,将函数信息写在system prompt中,否则写在user prompt中)。返回的函数调用将包含在文本字符串中,需要解析成规范的函数调用格式后使用。同样以OpenAI模型调用为例:
// 可调用的函数列表
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取当前天气",
"parameters": {...},
}
},
{
"type": "function",
"function": {
"name": "get_n_day_weather_forecast",
"description": "获取N天的天气预报",
"parameters": {...},
}
},
]
system_prompt = "你是调用函数解决问题的专家" # 设置system prompt,这里给出示例的system prompt
system_prompt = system_prompt + """下面是你可以调用的函数:[{"name": "get_current_weather","description": "获取当前天气","parameters": {...}},
{"name": "get_n_day_weather_forecast","description": "获取N天的天气预报","parameters": {...}}]"""
messages = [{"role":"system", "content":system_prompt},
{"role":"user", "content":"我在北京.接下来五天的天气怎么样"}] # 用户的提问
tool_choice="auto" # 模型自己判断要不要调用函数
model="" # 指定模型
// 将用户的提问和可调用的函数列表发送给模型,模型自己判断要不要调用函数
response = client.chat.completions.create(
model=model,
messages=messages
)
模型的返回结果格式如下:(content字段中是模型回复内容)
{"role":"assistant",
"content":"根据用户的需求,要查询北京未来五天的天气情况,正确的函数调用为:get_n_day_weather_forecast(location="北京",
format="celsius",
num_days=5)"}
评分标准
在初始状态state A下,执行ground truth给出的函数调用,系统的状态改变为state B;
在同样的初始状态state A下,执行被测评模型给出的函数调用,系统的状态改变为state C;
检查state B和state C两个状态下的系统中包含的对象和对象的属性是否完全相同,相同则验证通过。否则模型回复视为错误。
在每轮对话中,模型根据用户的任务需求和环境反馈生成了多个函数调用:[func_name1(params_name1=params_value1, params_name2=params_value2...), func_name2(params), func_name3(params), ...],按照模型生成的顺序执行这些函数调用,得到每个函数调用的返回结果集合1: (return 1, return 2, return 3, ...)
ground truth中给出了完成任务必须的函数调用,ground truth 中的函数调用:[func_name1(params_name1=params_value1, params_name2=params_value2...), func_name2(params), ...]。按照ground truth的函数调用顺序执行,得到每个函数的调用结果集合2:(groundtruth return 1, ground truth return 2, ...)
判断集合1中是否包含了集合2中的所有元素,包含则验证通过,否则视为错误。
评估案例
AgentCLUE采用多轮交互方式进行测评,会对每一轮对话采用相同的评分标准进行检查。因此,我们以基础多轮对话任务的一道问题作为示例,展示使用Function Calling模式调用模型的情况下,一轮交互中,从用户向模型提问,到模型结束本轮任务的过程,以及评价结果的解读。
【系统初始化参数】(初始化系统时,当前工作路径为/小李,该路径下包含名为'workspace'的文件夹,在'workspace'文件夹中包含了'exp.txt'和'.hidden_file'文件,以及'spcl'文件夹)
{"initial_config":
{"ClueFileSystem":
{"root": {"小李": {"type": "directory",
"contents": {"workspace": {"type": "directory",
"contents": {
"exp.txt": {"type": "file", "content": "这是一个exp文件。\n 今天我们在这里欢聚一堂。\n为的是庆祝这一圆满的胜利成果!\n 我们终于完成了这一宇宙的壮举。"},
"spcl": {"type": "directory", "contents": {}},
".hidden_file": {"type": "file", "content": "这是隐藏文件。"}}}}}}}}
}
【Ground truth】 (人类标注的准确函数调用答案):
["pwd()", "ls(a=True)"]
【模型完成用户提出的需求的交互过程】
// 1. User提出的任务需求。(可调用的Function列表过长,此处省略)
{"role": "user", "content": "我是小李,请帮我检查一下当前目录是否在我名下,并列出当前目录中所有可见以及隐藏的内容。"},
// 2. 模型的第一次回复,tool_calls中是模型认为需要调用的函数,
{"content": null, "role": "assistant", "tool_calls": [{"function": {"arguments": "{}", "name": "pwd"}, "id": "call_aG9HnNBqEE2g6F8N4INNSW2X", "type": "function"}]},
// 3. 从模型回复中提取可执行的函数调用: "pwd()"
{"model_response_decoded":"pwd()"},
// 4. 执行提取的函数调用得到函数返回结果:{"current_working_directory":"小李"}
{"role": "tool", "content": "{\"current_working_directory\": \"/小李\"}", "tool_call_id": "call_aG9HnNBqEE2g6F8N4INNSW2X"},
// 5. 将第4步中函数返回结果,加入到对话历史中,再次发送给模型作为环境反馈信息,帮助模型进行思考改进(self correct),模型再次给出回答。tool_calls中是模型认为需要调用的函数。
{"content": null, "role": "assistant", "tool_calls": [{"function": {"arguments": "{\"a\":true}", "name": "ls"}}]},
// 6. 从模型回复中提取可执行的函数调用:"ls(a=True)"
{"model_response_decoded":"ls(a=True)"}
// 7. 执行提取的函数调用得到函数返回结果:{"current_directory_content": ["workspace"]}
{"role": "tool", "content": "{\"current_directory_content\": [\"workspace\"]}", "tool_call_id": "call_KVVpHSZv96JuDFz8SY5rkWVC"},
// 8. 将第7步中函数返回结果,加入到对话历史中,再次发送给模型作为环境反馈信息,帮助模型,模型再次给出回答。
{"content": "你当前的目录是 `/小李`。在该目录中,有以下内容(包括隐藏文件):\n- workspace", "role": "assistant"}
// 9. 模型不再给出function_call调用,结合函数执行结果对user的问题进行回答,本轮任务结束,将进行下一轮user提问。
【执行评价】:
函数调用执行结果对比:
依次执行ground truth中的函数,得到返回结果1:
[{"current_working_directory":"小李"}, {"current_directory_content": ["workspace"]}]
执行模型回复的函数调用,得到返回结果2:
[{"current_working_directory":"小李"}, {"current_directory_content": ["workspace"]}]
以上两项验证均通过,模型在本轮中成功完成了用户提出的任务需求。
评分方法
# 测评邀请
时间规划
测评流程
1.邮件申请
2.意向沟通
3.参测确认与协议流程
4.提供模型API及文档,文档中需说明参与测评的模型调用方式(Function Calling或Prompting)
5.获得测评报告
接口规范
https://cookbook.openai.com/examples/how_to_call_functions_with_chat_models#executing-sql-queries
https://bigmodel.cn/dev/howuse/functioncall
在测评中,为帮助模型进行自我反思,需要将函数调用的执行结果加入对话历史中传给模型,以再次获取答案,例如,OpenAI的模型通过在messages中增加'tool'角色来实现上传函数执行结果。
messages.append({
"role":"tool",
"tool_call_id":tool_call_id,
"name": tool_function_name, # 调用的函数名称
"content":results # 函数执行的返回结果
})
可参考:
https://cookbook.openai.com/examples/how_to_call_functions_with_chat_models#executing-sql-queries